var board = new Array();
var score = 0;
var hasConflicted = new Array();

var startX = 0;
var startY = 0;
var endX = 0;
var endY = 0;

$(document).ready(function(){
    prepareForMobil();
    newGame();
});

function prepareForMobil() {
    if (documentWidth > 500) {
        mainWidth = 500;
        cellSpace = 20;
        cellSideLength = 100;
    }else {
        $("main").css("width", mainWidth - 2 * cellSpace);
        $("main").css("height", mainWidth - 2 * cellSpace);
        $("main").css("padding", cellSpace);
        $("main").css("border-radius", 0.02 * mainWidth);

        $(".cell").css("width", cellSideLength);
        $(".cell").css("height", cellSideLength);
        $(".cell").css("border-radius", 0.02 * cellSideLength);
    }
}

function newGame() {
    // 初始化棋盘格
    init();
    // 随机两个格子生成数字
    generateOneNumber();
    generateOneNumber();
}

function init() {
    for (var i = 0; i < 4; i++) {
        for (var j = 0; j < 4; j++) {
            var cell = $("#cell-" + i + "-" + j);
            cell.css("top", getPosTop(i, j));
            cell.css("left", getPosLeft(i, j));
        }
    }

    for (var i = 0; i < 4; i++) {
        board[i] = new Array();
        hasConflicted[i] = new Array();
        for(var j = 0; j <4; j++){
            board[i][j] = 0;
            hasConflicted[i][j] = false;
        }
    }

    updateBoardView();
    score = 0;
    updateScore(score);
}

function updateBoardView() {
    $(".number-cell").remove();
    for (var i = 0; i < 4; i++) {
        for (var j = 0; j < 4; j++) {
            $("main").append('<div class="number-cell" id="number-cell-' + i + '-' + j + '"></div>');
            var theNumberCell = $("#number-cell-" + i + "-" + j);
            if(board[i][j] == 0){
                theNumberCell.css("width", "0px");
                theNumberCell.css("heiht", "0px");
                theNumberCell.css("top", getPosTop(i, j) + cellSideLength / 2);
                // console.log(getPosTop(i, j) + 50 + "px");
                theNumberCell.css("left", getPosLeft(i, j) + cellSideLength /2);
                // console.log(getPosLeft(i, j) + 50 + "px");
            }else {
                theNumberCell.css("width", cellSideLength);
                theNumberCell.css("heiht", cellSideLength);
                theNumberCell.css("top", getPosTop(i, j));
                theNumberCell.css("left", getPosLeft(i, j));
                theNumberCell.css("background-color", getNumberBackgroundColor(board[i][j]));
                theNumberCell.css("color", getNumberColor(board[i][j]));
                theNumberCell.text(board[i][j]);

            }

            hasConflicted[i][j] = false;

        }
    }
    $(".number-cell").css("line-height", cellSideLength + "px");
    $(".number-cell").css("font-size", 0.6 * cellSideLength + "px");
}

function generateOneNumber() {
    if(noSpace(board)){
        console.log("generateOneNumber(): nospeace,will false");
        return false
    }else{
        var randomPosX = parseInt(Math.floor(Math.random() * 4));
        var randomPosY = parseInt(Math.floor(Math.random() * 4));
        var times = 0;
        while (times < 50) {
            if(board[randomPosX][randomPosY] == 0){
                break;
            }
            randomPosX = parseInt(Math.floor(Math.random() * 4));
            randomPosY = parseInt(Math.floor(Math.random() * 4));
        }
        if (times == 50) {
            for (var i = 0; i < 4; i++) {
                for (var j = 0; j < 4; j++) {
                    if(board[i][j] == 0){
                        randomPosX = i;
                        randomPosY = j;
                    }
                }
            }
        }

        var randomNumber = Math.random() < 0.5 ? 2 : 4;
        board[randomPosX][randomPosY] = randomNumber;
        showNumberWithAnimation(randomPosX, randomPosY, randomNumber);

        return true;
    }
}

$(document).keydown(function(event) {
    event.preventDefault();
    console.log("key down");
    // noSpace(board);
    switch (event.keyCode) {
        case 37:
            if(moveLeft()){
                console.log("im left");
                setTimeout("generateOneNumber()", 200);
                // generateOneNumber();
                setTimeout("isGameOver()", 300);
                // isGameOver();
            }
            break;
        case 38:
            if(moveUp()){
                setTimeout("generateOneNumber()", 200);
                // generateOneNumber();
                setTimeout("isGameOver()", 300);
                // isGameOver();
            }
            break;
        case 39:
            if(moveRight()){
                setTimeout("generateOneNumber()", 200);
                // generateOneNumber();
                setTimeout("isGameOver()", 300);
                // isGameOver();
            }
            break;
        case 40:
            if(moveDown()){
                setTimeout("generateOneNumber()", 200);
                // generateOneNumber();
                setTimeout("isGameOver()", 300);
                // isGameOver();
            }
            break;
        default:

    }
});

document.addEventListener("touchstart", function(event) {
    startX = event.touches[0].pageX;
    startY = event.touches[0].pageY;
})

document.addEventListener("touchend", function(event) {
    endX = event.changedTouches[0].pageX;
    endY = event.changedTouches[0].pageY;
    var deltaX = endX - startX;
    var deltaY = endY - startY;

    if ((Math.abs(deltaX) < 0.3 * documentWidth) && (Math.abs(deltaY) < 0.3 * documentWidth)) {
        return;
    }

    if(Math.abs(deltaX) >= Math.abs(deltaY)){
        if (deltaX > 0) {
            //right
            if(moveRight()){
                setTimeout("generateOneNumber()", 200);
                // generateOneNumber();
                setTimeout("isGameOver()", 300);
                // isGameOver();
            }
        }else {
            //left
            if(moveLeft()){
                console.log("im left");
                setTimeout("generateOneNumber()", 200);
                // generateOneNumber();
                setTimeout("isGameOver()", 300);
                // isGameOver();
            }
        }
    }else {
        if(deltaY > 0){
            //down
            if(moveDown()){
                setTimeout("generateOneNumber()", 200);
                // generateOneNumber();
                setTimeout("isGameOver()", 300);
                // isGameOver();
            }
        }else {
            //up
            if(moveUp()){
                setTimeout("generateOneNumber()", 200);
                // generateOneNumber();
                setTimeout("isGameOver()", 300);
                // isGameOver();
            }
        }
    }
})

// TODO: 结束游戏判断
function isGameOver() {
    if(noSpace(board) && noMove(board)){
        gameOver();
    }
}

function gameOver() {
    alert("GameOver!!!");
    // console.log("gameOver");
}

function moveLeft() {
    if(!canMoveLeft(board)){
        return false;
    }else {
        for (var i = 0; i < 4; i++) {
            for (var j = 1; j < 4; j++) {
                if(board[i][j] != 0){
                    for (var k = 0; k < j; k++) {
                        if((board[i][k] == 0) && noBlockX(i, k, j, board)){
                            // TODO: move
                            showMoveAnimation(i, j, i, k);
                            board[i][k] = board[i][j];
                            board[i][j] = 0;
                            continue;
                        }else if ((board[i][k] == board[i][j]) && noBlockX(i, k, j, board) && !hasConflicted[i][k]){
                            // TODO: move
                            showMoveAnimation(i, j, i, k);
                            // TODO: add
                            board[i][k] += board[i][j];
                            board[i][j] = 0;
                            // TODO: set flag
                            hasConflicted[i][k] = true;
                            // TODO: score add and show
                            score += board[i][k];
                            updateScore(score);
                            continue;
                        }
                    }

                }
            }
        }
        setTimeout("updateBoardView()", 200);
        // updateBoardView();
        return true;
    }
}

function moveRight() {
    if(!canMoveRight(board)){
        return false;
    }else {
        for (var i = 0; i < 4; i++) {
            for (var j = 2; j > -1; j--) {
                if(board[i][j] != 0){
                    for (var k = 3; k > j; k--) {
                        if((board[i][k] == 0) && noBlockX(i, j, k, board)){
                            // TODO: move
                            showMoveAnimation(i, j, i, k);
                            board[i][k] = board[i][j];
                            board[i][j] = 0;
                            continue;
                        }else if ((board[i][k] == board[i][j]) && noBlockX(i, j, k, board) && !hasConflicted[i][k]) {
                            // TODO: move
                            showMoveAnimation(i, j, i, k);
                            // TODO: add
                            board[i][k] += board[i][j];
                            board[i][j] = 0;
                            // TODO: set flag
                            hasConflicted[i][k] = true;
                            // TODO: score add and show
                            score += board[i][k];
                            updateScore(score);
                            continue;
                        }
                    }

                }
            }
        }
        setTimeout("updateBoardView()", 200);
        // updateBoardView();
        return true;
    }
}

function moveUp() {
    if(!canMoveUp(board)){
        return false;
    }else {
        for (var j = 0; j < 4; j++) {
            for (var i = 1; i < 4; i++) {
                if(board[i][j] != 0){
                    for (var k = 0; k < i; k++) {
                        if((board[k][j] == 0) && noBlockY(j, k, i, board)){
                            // TODO: move
                            showMoveAnimation(i, j, k, j);
                            board[k][j] = board[i][j];
                            board[i][j] = 0;
                            continue;
                        }else if ((board[k][j] == board[i][j]) && noBlockY(j, k, i, board) && !hasConflicted[k][j]) {
                            // TODO: move
                            showMoveAnimation(i, j, k, j);
                            // TODO: add
                            board[k][j] += board[i][j];
                            board[i][j] = 0;
                            // TODO: set flag
                            hasConflicted[k][j] = true;
                            // TODO: score add and show
                            score += board[k][j];
                            updateScore(score);
                            continue;
                        }
                    }

                }
            }
        }
        setTimeout("updateBoardView()", 200);
        // updateBoardView();
        return true;
    }
}

function moveDown() {
    if(!canMoveDown(board)){
        return false;
    }else {
        for (var j = 0; j < 4; j++) {
            for (var i = 2; i > -1; i--) {
                if(board[i][j] != 0){
                    for (var k = 3; k > i; k--) {
                        if((board[k][j] == 0) && noBlockY(j, i, k, board)){
                            // TODO: move
                            showMoveAnimation(i, j, k, j);
                            board[k][j] = board[i][j];
                            board[i][j] = 0;
                            continue;
                        }else if ((board[k][j] == board[i][j]) && noBlockY(j, i, k, board) && !hasConflicted[k][j]) {
                            // TODO: move
                            showMoveAnimation(i, j, k, j);
                            // TODO: add
                            board[k][j] += board[i][j];
                            board[i][j] = 0;
                            // TODO: set flag
                            hasConflicted[k][j] = true;
                            // TODO: score add and show
                            score += board[k][j];
                            updateScore(score);
                            continue;
                        }
                    }

                }
            }
        }
        setTimeout("updateBoardView()", 200);
        // updateBoardView();
        return true;
    }
}
